package cn.uc.ucgc.community.upgrade.conf.task;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.uc.ucgc.community.upgrade.Constants;
import cn.uc.ucgc.community.upgrade.Task;
import cn.uc.ucgc.community.upgrade.Utils;
import cn.uc.ucgc.community.upgrade.conf.JobType;
import cn.uc.ucgc.community.upgrade.conf.MacroItem;
import cn.uc.ucgc.community.upgrade.conf.ModifyJob;

/**
 * 需要修改的任务
 * 
 * @author yuyj@ucweb.com
 * @createDate 2014-3-13
 *
 */
public class ModifyTask extends Task {
    private static final Logger logger = LoggerFactory.getLogger(ModifyTask.class);
    //任务信息
    private List<ModifyJob> jobs;
    private File macroFile;

    public ModifyTask(List<ModifyJob> jobs, File macroFile) {
        super.setTaskDesc("Modify File Task");
        this.jobs = jobs;
        this.macroFile = macroFile;
    }
    
    public List<ModifyJob> getJobs() {
        return jobs;
    }

    @Override
    public void doTask(StringBuilder sb) throws IOException, DocumentException {
        if (null == jobs || jobs.isEmpty()) {
            sb.append(Constants.TASK_RESULT_NOTASK_SUFFIX);
            return;
        }
        //首先将XML/prop任务分开
        List<ModifyJob> propJobs = new ArrayList<ModifyJob>();
        List<ModifyJob> xmlJobs = new ArrayList<ModifyJob>();
        for (ModifyJob job : jobs) {
            if (null == job) {
                continue;
            }
            if (JobType.PROP == job.getType()) {
                propJobs.add(job);
            } else {
                xmlJobs.add(job);
            }
        }
        //读取对应的宏配置文件
        Properties macroProp = Utils.getPropValues(macroFile);
        logger.warn("Need modify prop file count:{}", propJobs.size());
        //对prop类型的做处理
        doPropJobs(propJobs, macroProp);
        logger.warn("Need modify xml file count:{}", xmlJobs.size());
        //对xml类型的做处理
        doXmlJobs(xmlJobs, macroProp);
    }

    private void doPropJobs(List<ModifyJob> propJobs, Properties macroProp) throws IOException {
        //读取prop配置文件，并将对应需要修改的数据更新，然后保存文件
        for (ModifyJob job : propJobs) {
            //1)获取对应待操作的文件
            File filePath = job.getSrcPath();
            logger.info("prop modify:{}", filePath.getCanonicalPath());
            List<MacroItem> items = job.getModifyItems();
            if (null == items || items.isEmpty()) {
                logger.warn("no modify items");
                continue;
            }
            //从原文件中读取，并收集好需要替换的key
            Properties properties = Utils.getPropValues(filePath);
            Map<String, String> replaceProps = new HashMap<String, String>();
            for (MacroItem item : items) {
                //该配置文件，需要修改的项
                String key = item.getName();
                String originalVal = properties.getProperty(key);
                //如果目标文件中不存在，直接打印日志，走后续逻辑
                if (null == originalVal) {
                    logger.warn("no key:{}", key);
                    continue;
                }
                //首先尝试从宏配置文件中读取
                String macroKey = item.getMacroKey();
                String realVal = macroProp.getProperty(macroKey);
                if (null == realVal) {
                    logger.warn("no macroVal,the macroKey:{}", macroKey);
                    //如果没有的话，则直接丢弃掉该配置项
                    continue;
                }
                replaceProps.put(key, realVal);
            }
            //根据收集的数据，重写目标文件
            Utils.modifyPropFile(filePath, replaceProps);
        }
    }

    private void doXmlJobs(List<ModifyJob> propJobs, Properties macroProp) throws IOException,
            DocumentException {
        //对xml做修改的，只能是叶子节点
        for (ModifyJob job : propJobs) {
            //1)获取对应待操作的文件
            File filePath = job.getSrcPath();
            logger.info("xml modify:{}", filePath.getCanonicalPath());
            List<MacroItem> items = job.getModifyItems();
            if (null == items || items.isEmpty()) {
                logger.warn("no modify items");
                continue;
            }
            //收集数据
            SAXReader srcReader = new SAXReader();
            Document srcDom = srcReader.read(filePath);
            for (MacroItem item : items) {
                //首先要从源xml文件中获取对应的数据，这里是直接定义成dom4j的xPath格式
                String srcKeyPath = item.getName();
                Node srcVal = srcDom.selectSingleNode(srcKeyPath);
                if (null == srcVal) {
                    logger.warn("no srcKeyPath:{}", srcKeyPath);
                    continue;
                }
                //这里直接操作目标的dom
                Element srcEle = (Element) srcVal;
                if (!srcEle.isTextOnly()) {
                    //非叶子节点，也直接丢弃
                    logger.warn("srcKeyPath:{} not a leaf", srcKeyPath);
                    continue;
                }

                //首先尝试从宏配置文件中读取
                String macroKey = item.getMacroKey();
                String realVal = macroProp.getProperty(macroKey);
                if (null == realVal) {
                    logger.warn("no macroVal,the macroKey:{}", macroKey);
                    //如果没有的话，则直接丢弃掉该配置项
                    continue;
                }
                //直接将文本替换过去
                srcEle.setText(realVal);
            }
            //保存至文件
            Utils.saveDom2Xml(srcDom, filePath);
        }
    }
}